<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TreeComboBox Demo for dojo 1.4</title>

<style type="text/css">
@import "script/dojo-1.4.3/dojo/resources/dojo.css";
@import "script/dojo-1.4.3/dijit/themes/tundra/tundra.css";

@import "script/dojo-1.4.3/dojox/layout/resources/FloatingPane.css";
@import "script/dojo-1.4.3/dojox/layout/resources/ResizeHandle.css";

body {
    font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
    font-size: 11px;
}

#debugPanel pre {
    font-family: "Lucida Console", "Courier New", Courier, monospace;

}

div.container {
    border: 0px solid green;
    margin: 10px;
}
</style>

<script type="text/javascript">
var djConfig = {
    isDebug: true,
    parseOnLoad: true,
    locale: "zh",
    extraLocale: ["en"]
};
</script>
<script type="text/javascript" src="script/dojo-1.4.3/dojo/dojo.js"></script>
<script type="text/javascript">
    dojo.require("dojo.data.ItemFileReadStore");
    dojo.require("dojo.data.ItemFileWriteStore");
    dojo.require("dojo.date.locale");
    dojo.require("dojo.parser");

    dojo.require("dijit.Dialog");
    dojo.require("dijit.form.CheckBox");
    dojo.require("dijit.form.ComboBox");
    dojo.require("dijit.form.Button");
    dojo.require("dijit.form.DateTextBox");
    dojo.require("dijit.form.FilteringSelect");
    dojo.require("dijit.form.RadioButton");
    dojo.require("dijit.form.TextBox");
    dojo.require("dijit.TitlePane");

    dojo.require("dijit.tree.ForestStoreModel");
    dojo.require("dijit.tree.TreeStoreModel");
    dojo.require("dijit.Tree");

    dojo.require("dojox.layout.FloatingPane");
    dojo.require("dojox.layout.ResizeHandle");

    dojo.require("com.ibm.ria.TreeComboBox");
</script>
<script type="text/javascript">
function getDebugMsg() {
    var args = [];
    for (var i = 0; i< arguments.length; i += 1) {
        args.push(arguments[i]);
    }
    var msg = args.join(" ");
    return msg;
}

function debug(messages) {
    var msg = getDebugMsg.apply(null, arguments);
    console.debug(msg);

    var msgDiv = dojo.byId("debugPanelContent");
    msgDiv.innerHTML = msg;
}

function append(messages) {
    var msg = getDebugMsg.apply(null, arguments);

    var msgDiv = dojo.byId("debugPanelContent");
    msgDiv.innerHTML += "\n" + msg;
}

function show(id) {
    var element = dojo.byId(id);
    if (element.style.display === "none") {
        element.style.display = "";
    }
}

function hide(id) {
    var element = dojo.byId(id);
    element.style.display = "none";
}
</script>
<style type="text/css">
@import "css/rounded-button.css";
@import "css/rounded-corners.css";

body {
    padding: 10px;
}

.TreeComboBoxPopUp {
    min-width: 100px;
    min-height: 50px;
    max-width: 400px;
    max-height: 400px;
    overflow: auto;
    border: 1px solid black;
}

/* Selected tree node style */
.tundra .dijitTreeNodeSelected .dijitTreeLabel {
    background-color: #3559ac;
    color: white;
}

.tundra .dijitTreeNodeHover {
    /*background-image: none;
    background-color: #3559ac;
    color: white;*/
}
</style>
<script type="text/javascript">
var GlobalVariables = {
    "TreeSelectorQueries": {
        "all": {top : true},
        "dsp": {dsp : true},
        "fav": {fav : true}
    }
};
dojo.addOnLoad(function() {
    debug("loaded");

    var productGroupSelector = dijit.byId("productGroupSelector");
    var store = productGroupSelector.store;

    var parentTree = dijit.byId("parentTree");
    var childTree = dijit.byId("childTree");

    dojo.connect(productGroupSelector, "onChange", function(value) {

        // update tree for arrow icons
        var _setArrowIcons = function(rootItem) {
            // reload child tree
            loadTreeItems(store, rootItem, "children", updateTooltipTree, {
                tooltipParentWidget: dijit.byId("arrowDownButton"),
                treeId: "childTree",
                store: store,
                rootItem: rootItem
            });

            // reload parent tree
            loadTreeItems(store, rootItem, "parents", updateTooltipTree, {
                tooltipParentWidget: dijit.byId("arrowUpButton"),
                treeId: "parentTree",
                store: store,
                rootItem: rootItem
            });
        };

        var name = value;
        store.fetch({
            query: {name: name},
            onComplete: function(items) {
                if (!items || !items.length || items.length < 1) {
                    return;
                }

                var item = items[0];
                _setArrowIcons(item);
            }
        });
    });

});

function destroyTree(tree) {
    tree.destroy();
}

function createTree(id, containerNode, treeModel) {
    var tree = dijit.byId(id);
    if (tree) {
        destroyTree(tree);
    }

    var showRoot = true;
    if (treeModel.isInstanceOf(dijit.tree.ForestStoreModel)) {
        showRoot = false;
    } 
    tree = new dijit.Tree({
        id: id,
        model: treeModel,
        showRoot: showRoot,
        persist: false
    });
    containerNode.appendChild(tree.domNode);
    tree.startup();
}

function changeModel(tree, container, treeModel, showRoot) {
    var id = tree.id;
    tree.destroy();

    tree = new dijit.Tree({
        id: id,
        model: treeModel,
        showRoot: showRoot,
        persist: false
    });
    container.appendChild(tree.domNode);
    tree.startup();
}

function callbackParentItems(item, parentItems) {
    callbackResultItems(item, parentItems, "parent");
}

function callbackChildItems(item, childItems) {
    callbackResultItems(item, childItems, "child");
}

function callbackResultItems(item, resultItems, type) {
    var selector = dijit.byId("productGroupSelector");
    var store = selector.store;

    var ids = [];
    dojo.forEach(resultItems, function(resultItem) {
        var id = store.getIdentity(resultItem);
        ids.push(id);
    });
    var pattern = ids.join("|");
    var regExp = new RegExp(pattern, "mi");
    var query = {
        id: pattern
    };
    var itemId = store.getIdentity(item);
    append("item:", itemId, "=>", type + ":", regExp.source);
}


// Click parent icon.
function showParentSelectorTooltip(node) {
    var tooltip = dijit.byId("parentSelectorTooltip");
    showSelectorTooltip(tooltip, node);
}

// Click child icon.
function showChildSelectorTooltip(node) {
    var tooltip = dijit.byId("childSelectorTooltip");
    showSelectorTooltip(tooltip, node);
}

function showSelectorTooltip(tooltip, aroundNode) {
    dijit.popup.open({
        //parent: parentWidget,
        popup: tooltip,
        around: aroundNode,
        onExecute: function(){
            closeTooltip(tooltip);
        },
        onCancel: function(){
            closeTooltip(tooltip);
        },
        onClose: function(){
            console.debug("onClose")
        }
    });
}

function closeTooltip(tooltip) {
    dijit.popup.close(tooltip);
}

// Click OK in select parent tooltip dialog.
function focusParent() {
    var parentTree = dijit.byId("parentTree");
    focusNodeFromTree(parentTree);
}

// Click OK in select child tooltip dialog.
function focusChild() {
    var childTree = dijit.byId("childTree");
    focusNodeFromTree(childTree);
}

function focusNodeFromTree(tree) {
    var selector = dijit.byId("productGroupSelector");

    var item = tree.attr("selectedItem");
    var name = tree.model.store.getValue(item, "name");
    debug("selected item:", name);

    selector.attr("item", item);
}

function loadTreeItems(store, item, attributeName, callback, callbackArgs) {
    var results = [];
    callbackArgs.subItems = results;

    if (!item) {
        callback.call(null, callbackArgs);
        return;
    }

    var resultItems = store.getValues(item, attributeName);
    if (resultItems.length < 1) {
        callback.call(null, callbackArgs);
    }

    for (var i = 0; i < resultItems.length; i+=1) {
        var resultItem = resultItems[i];

        if(!store.isItemLoaded(resultItem)){
            store.loadItem({
                item: resultItem,
                onItem: function(loadedItem) {
                    results.push(loadedItem);
                    if (i === resultItems.length - 1) {
                        callback.call(null, callbackArgs);
                    }
                },
                onError: function() {
                    console.warn("error loading parent item");
                }
            });
        } else {
            results.push(resultItem);
            if (i === resultItems.length - 1) {
                callback.call(null, callbackArgs);
            }
        }
    }
}

function updateTooltipTree(args) {

    var treeId = args.treeId;
    var store = args.store;
    var rootItem = args.rootItem;
    var subItems = args.subItems;
    var tooltipParentWidget = args.tooltipParentWidget;

    callbackParentItems.call(null, rootItem, subItems);

    if (subItems.length < 1) {
        tooltipParentWidget.attr("disabled", true);
        return;
    }

    tooltipParentWidget.attr("disabled", false);

    var rootIdentity = store.getIdentity(rootItem);
    var queryTreeRoot = {
        id: rootIdentity
    };
    var tree = dijit.byId(treeId);
    tree.model.query = queryTreeRoot;
    tree.model.root = null;

    // re-create tooltip tree
    var treeContainerNode = tree.domNode.parentNode;
    createTree(treeId, treeContainerNode, tree.model);
}

function changeStoreForSelector(selector, store) {
    if (selector) {
        var identity = null;
        var selectedItem = selector.attr("item");
        if (selectedItem) {
            identity = selector.store.getIdentity(selectedItem);
        }
        selector.attr("store", store); // update store
        selector.attr("identity", identity); // restore selected item
        selector.attr("disabled", false);
    }
}

// click change store button
function changeStore(url) {
    var productGroupSelector = dijit.byId("productGroupSelector");
    var store = new dojo.data.ItemFileWriteStore({url: url});
    store.fetch({
        onComplete: function(items) {
            changeStoreForSelector(productGroupSelector, store);
        }
    });
}

// click focus node button
function focusNode(path) {
    var selector = dijit.byId("productGroupSelector");

    if (!dojo.isArray(path)) {
        path = [].push(path);
    }

    var length = path.length;
    var identity = path[length-1];

    var item = selector.store._getItemByIdentity(identity);
    if (item) {
        selector.attr("item", item);
    }
}
</script>
</head>
<body class="tundra">

  <!-- Debug Panel -->
  <div id="debugPanel" dojoType="dojox.layout.FloatingPane" title="Debug Panel" resizable="true" dockable="true" style="position: absolute; top: 300px; left: 20px; width: 800px; height: 150px;">
    <pre id="debugPanelContent"></pre>
  </div>
  <hr />

  <div id="main" class="container">
    <div dojoType="dojo.data.ItemFileReadStore" jsId="nodeStore" url="./data/tree.json"></div>
    <div dojoType="dojo.data.ItemFileWriteStore" jsId="javaStore" url="./data/tree_java.json"></div>
    <div dojoType="dojo.data.ItemFileWriteStore" jsId="productGroupStore" url="./data/tree-multiple_parent.json"></div>
    <div dojoType="dojo.data.ItemFileWriteStore" jsId="productGroupStore_tree" url="./data/product_group_tree.json"></div>
    <div dojoType="dojo.data.ItemFileWriteStore" jsId="productGroupStore_flat" url="./data/product_groups.json"></div>

    <div dojoType="dijit.tree.ForestStoreModel" jsId="productGroupModel" store="productGroupStore" rootId="$root$" rootLabel="ROOT" childrenAttrs="children" deferItemLoadingUntilExpand="true" query="{type:'root'}"></div>
    <div dojoType="dijit.tree.ForestStoreModel" jsId="forestModel" store="javaStore" rootId="$root$" rootLabel="ROOT" childrenAttrs="children" deferItemLoadingUntilExpand="true" query="{type:'root'}"></div>

    <div dojoType="dijit.tree.TreeStoreModel" jsId="parentTreeModel" store="javaStore" childrenAttrs="parents" deferItemLoadingUntilExpand="true" query="{id:'$root$'}"></div>
    <div dojoType="dijit.tree.TreeStoreModel" jsId="childTreeModel" store="javaStore" childrenAttrs="children" deferItemLoadingUntilExpand="true" query="{id:'$root$'}"></div>

    <div id="treePanel" dojoType="dijit.TitlePane" title="ComboBox" style="">
      <div id="treePanelContent" style="position:relative; padding: 10px; border:1px solid black;">

        <!-- TreeComboBox -->
        <label for="productGroupSelector">Class type:</label> <input id="productGroupSelector" dojoType="com.ibm.ria.TreeComboBox" value="-- Select a class type --" store="javaStore" searchAttr="name" query="{top: true}" queryExpr="*${0}*" highlightMatch="first" style="width: 200px;" />

        <!-- ArrowDown DropDownButton -->
        <div id="arrowDownButton" dojoType="dijit.form.DropDownButton" iconClass="iconDownArrow" showLabel="true" autoWidth="false" disabled="disabled">
          <span>⬇⬇</span>
          <div id="childSelectorTooltip" dojoType="dijit.TooltipDialog">
            <div><strong>Select a child item</strong></div>
            <!-- Tree -->
            <div class="TreeComboBoxPopUp">
              <div id="childTree" dojoType="dijit.Tree" model="childTreeModel" showRoot="false" persist="false"></div>
            </div>
            <button id="selectChildButton" dojoType="dijit.form.Button" type="submit" onclick="focusChild();">Select</button>
          </div>
        </div>

        <!-- ArrowUp DropDownButton -->
        <div id="arrowUpButton" dojoType="dijit.form.DropDownButton" iconClass="iconUpArrow" showLabel="true" autoWidth="false" disabled="disabled">
          <span>⬆⬆</span>
          <div id="parentSelectorTooltip" dojoType="dijit.TooltipDialog">
            <div><strong>Select a parent item</strong></div>
            <!-- Tree -->
            <div class="TreeComboBoxPopUp">
              <div id="parentTree" dojoType="dijit.Tree" model="parentTreeModel" showRoot="false" persist="false"></div>
            </div>
            <button id="selectParentButton" dojoType="dijit.form.Button" type="submit" onclick="focusParent();">Select</button>
          </div>
        </div>

        <!-- Resize Handle -->
        <div id="resizeHandle" dojoType="dojox.layout.ResizeHandle" targetId="treePanelContent"></div>
      </div>
    </div>
    <hr />

  <!-- Button Panel -->
  <div dojoType="dojo.dnd.Moveable">
    <div id="buttonPanel" dojoType="dijit.TitlePane" title="Button Panel" style="">

      <div dojoType="dijit.form.Button" onClick="changeStore('./data/productgroups/$user-division-designated-products.json');">Change store: Division starting points</div>
      <div dojoType="dijit.form.Button" onClick="changeStore('./data/productgroups/$user-designated-products.json');">Change store: My favorites</div>
      <div dojoType="dijit.form.Button" onClick="focusNode(['$root$', 'Iterable', 'Collection', 'List']);">focus List</div>
      <div dojoType="dijit.form.Button" onClick="focusNode(['$root$', 'Map', 'SortedMap', 'NavigableMap', 'TreeMap']);">focus TreeMap</div>
      <div dojoType="dijit.form.Button" onClick="focusNode(['$root$', 'Map', 'AbstractMap', 'HashMap', 'JSONObject']);">focus JSONObject</div>
      <div dojoType="dijit.form.Button" onClick="focusNode(['$root$', 'Iterable', 'Collection', 'List', 'AbstractList', 'ArrayList', 'JSONArray']);">focus JSONArray</div>

        <a id="up_arrow" href="javascript://" onclick="showParentSelectorTooltip(this);" title="select a parent" style="display: inline;">⬆⬆</a>
        <a id="down_arrow" href="javascript://" onclick="showChildSelectorTooltip(this);" title="select a child" style="display: inline;">⬇⬇</a>
    </div>
  </div>

</body>
</html>
